package xyz.lwm.lazycat.netpipe.common.endec;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import xyz.lwm.lazycat.netpipe.common.protocol.Headers;
import xyz.lwm.lazycat.netpipe.common.protocol.Message;
import xyz.lwm.lazycat.netpipe.common.protocol.MsgType;
import xyz.lwm.lazycat.netpipe.common.serial.Serialization;
import xyz.lwm.lazycat.utility.Assert;

import java.util.List;

/**
 * <h3>消息解码器</h3>
 * F|msgType|headersLength|headers|dataLength|data
 *
 * @author lwm
 */
class MessageDecoder extends MessageToMessageDecoder<ByteBuf> {

    private final Serialization serialization;

    public MessageDecoder(Serialization serialization) {
        this.serialization = serialization;
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
        // read magic number
        byte magic = msg.readByte();
        Assert.isTrue(magic == 'F', "magic number error");

        // read msgType
        MsgType msgType = MsgType.valueOf(msg.readInt());
        Assert.notNull(msgType, "msgType");

        // create message
        Message message = new Message(msgType);

        // read headers
        int headersLength = msg.readInt();
        if (headersLength > 0) {
            byte[] headersBytes = new byte[headersLength];
            msg.readBytes(headersBytes);
            Headers headers = serialization.deserialize(headersBytes, Headers.class);
            message.setHeaders(headers);
        }

        // read data
        int dataLength = msg.readInt();
        if (dataLength > 0) {
            byte[] data = new byte[dataLength];
            msg.readBytes(data);
            message.setData(data);
        }

        out.add(message);
    }

}
